/* ----------------------------------------------------------------------------

	pax.box.js Copyright (C) 2005, 2007, 2008 Mikkel Bergmann, Pointful

	Licence
	-------
	
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

	See lgpl.txt for licence details

---------------------------------------------------------------------------- */

/*
	Script: pax.box
		This class creates boxes for various purposes; it's a base class for window, 
		and used in various widget classes
		
	Author:
		Mikkel Bergmann, <http://www.pointful.com>

*/


var pax = pax || {};
pax.box = pax.box || {};

/*	Method: pax.box.show
	Shows a box at given position
	
	Parameters:
		id - DOM pointer for the window element
		message - The contents to put into the box (HTML)
		className - The CSS class name to assign to the box
		x - Horizontal (left) position for the box
		y - Vertical (top) position for the box
		target - DOM element to append the box to; if not specifed, we use the body element
		
	Example:
		(start code)
			<input type='text' id='pax.box.show.example'>
			[:.
				var pos = pax.util.getPosition( pax.$('pax.box.show.example') );
				pax.box.show( 'myWindow', '^ Hello world!', 'hintMessage', pos.x, pos.y + pos.height + 5 );
				
				exampleCleanup = function() { pax.box.hide( 'myWindow' ); };
			:]
		(end)
		This will create a box below the input box. It uses <pax.util.getPosition> to find the position of the element.
		Also note that exampleCleanup is just a hook for the example, that hides the window again, when you're done with it.
*/
pax.box.show = function( id, message, className, x, y, target, displayStyle ) {
	//	Only insert the box once.
	if( document.getElementById( id ) == null ) {
		//	Create a DIV
		var div = document.createElement('DIV');
		div.id = id;
		div.className = className;
		div.style.position = 'absolute';
		div.style.left = x;
		div.style.top = y;
		div.innerHTML = message;
		div.style.display = (displayStyle)? displayStyle: 'block';
		
		if( typeof(target) != 'undefined' )target.appendChild( div );
		else document['body'].appendChild( div );
	}
	else div = document.getElementById( id );

	if( div.style.zIndex < 1 )div.style.zIndex = 3;  // Ensure that the box has a positive zIndex.
	div.className = className;
	div.style.position = 'absolute';
	div.style.left = x + 'px';
	div.style.top = y + 'px';
	div.innerHTML = message;
	div.style.display = (displayStyle)? displayStyle: 'block';
	div.innerHTML = message;

	//	Add a transparent iFrame, so that selectboxes don't peep through in IE
	if( pax.isIe6Down ) {
		var pos = pax.util.getPosition( div );
		var frameId = div.id + '_iFrame';
		
		var myFrame = document.getElementById( frameId );
		
		// Only insert iFrame, if it doesn't already exist
		if( myFrame == null ) {
			myZIndex = div.style.zIndex - 1;      // Insert iFrame layer just below Div
			// The ugly string below is an iframe with the correct parameters.
			myFrame = "<iframe src=\"javascript:false;\" id=\"" + frameId + "\" scrolling=\"no\" width=\"" + pos.width + "px\" height=\"" + pos.height + "px\" frameborder=\"0\" style=\"position:absolute;top:" + pos.y + "px;left:" + pos.x + "px;z-index:"+myZIndex+";filter:'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)';\"></iframe>";

			if( typeof(target) != 'undefined' )div.insertAdjacentHTML('beforeBegin', myFrame);
			else document.body.insertAdjacentHTML('beforeEnd', myFrame);
			
			div.frameId = frameId;		// Save the frame id
			myFrame = document.getElementById( frameId );
		}

		// Set iFrame properties to be sure!
		if( myFrame ) {
			myFrame.width = div.offsetWidth;
			myFrame.height = div.offsetHeight;
			myFrame.style.top = pos.y + "px";
			myFrame.style.left = pos.x + "px";
			myFrame.style.display = 'block';	//div.style.display;
			myFrame.style.zIndex = div.style.zIndex - 1;
		}
	}
	
	pax.box.setPosition( div, x, y );

	return div;
};


/*	Method: pax.box.append
	Shows a box at given element, appending it into the dom, rather than showing it at a specific position
	
	Parameters:
		id - DOM pointer for the window element
		message - The contents to put into the box (HTML)
		className - The CSS class name to assign to the box
		target - which element to append the box to
		location - one of N, E, S, W
		
	Example:
		(start code)
			<input type='text' id='pax.box.append.example'>
			[:.
				pax.box.append( 'myWindow', 'Hello world!', 'hintMessage',  pax.$('pax.box.append.example'), 'E' );
				exampleCleanup = function() { pax.box.hide( 'myWindow' ); };
			:]
		(end)
		This will create a box to the right of the input box.
		Note that exampleCleanup is just a hook for the example, that hides the box again, when you're done with it.
*/
pax.box.append = function( id, message, className, target, location ) {
	//	Only insert the box once.
	var box = document.getElementById( id );
	if( ! box ) {
		//	Create a DIV
		box = document.createElement('DIV');
		box.id = id;
		box.setAttribute( 'id', id );
		if( typeof(target) != 'undefined' ) {
			if( location == 'N' || location == 'W') {
				target.parentNode.insertBefore( box, target );
			} else {
				//	The div must appear AFTER the target.
				//	We check for IE here, and use it's insertAdjacentHTML method, to make sure we don't get the dreaded "Uknown runtime" error...
				if( pax.isIe ) {
					target.insertAdjacentHTML('AfterEnd', '<span id="' + id + '"></span>' );
					box = pax.$( id );
				} else {
					//	Do it the "long" way
					var span1 = document.createElement('SPAN');
					target.parentNode.insertBefore( span1, target );
					var span2 = document.createElement('SPAN');
					target.parentNode.insertBefore( span2, target );
					target.parentNode.replaceChild( target, span1 );
					target.parentNode.replaceChild( box, span2 );
				}
			}
		} else document['body'].appendChild( box );
	}

	box.className = className;
	box.style.position = 'relative';
	box.innerHTML = message;

	box.style.display = ( location == 'N' || location == 'S' )? 'block': 'inline';

	return box;
};


/*	Method: pax.box.setPosition
	Sets the position and size of a box, plus size & position of the iFrame for IE.
	
*/
pax.box.setPosition = function( box, x, y ) {
	if( box.frameId ) {
		var ifr = document.getElementById( box.frameId );
		ifr.style.left = x + 'px';
		ifr.style.top = y + 'px';
		
		var pos = pax.util.getPosition( box );
		
		ifr.style.width = pos.width;
		ifr.style.height = pos.height;
	}
	box.style.left = x + 'px';
	box.style.top = y + 'px';
};

/*	Method: pax.box.showOnRight
	Shows a box 5 pixels to the left of an element, optionally fading it out after timeout seconds.
	
	Parameters:
		id - DOM pointer to the window element
		message - The contents to put into the box
		className - The CSS class name to assign to the box
		element - The element to place the box near
		timeout - Optionally specify in seconds how long the box is visible, 0 = don't hide
		distance - Optionally specify in pixels how far away, defualt = 5px
		
	Example:
		(start code)
			<input type='text' id='pax.box.showOnRight.example'>
			[:.
				pax.box.showOnRight( 'myBox', '<- Hello world!', 'hintMessage', pax.$('pax.box.showOnRight.example'), 7 );
			:]
		(end)
		
		This will create a box to the right of myElement, and remove it after 7 seconds, (default = 5 seconds).
*/
pax.box.showOnRight = function( id, message, className, element, timeout, distance ) {
	window.clearTimeout( element.hintMessageTimeout );
	var dims = pax.util.getPosition( element );
	distance = ( typeof(distance) != 'undefined' )? distance: 5;
	var box = pax.box.show( id, message, className, dims.x + dims.width + distance, dims.y );
	pax.css.opacity( box, 100 );
	
	if( typeof( timeout ) != 'undefined' && timeout != 0 ) {
		//	element.hintMessageTimeout = window.setTimeout( function(){ pax.box.hide( id, pax.fx.fadeOut ) }, timeout * 1000 );
		element.hintMessageTimeout = window.setTimeout( function(){ pax.box.hide( id, pax.fx.fadeOut, function(){ pax.box.destroy( id ); } ) }, timeout * 1000 );
	}
	
	return box;
};


/*	Method: pax.box.hide
	This will hide the given box, using the (optional) given function
	
	Parameters:
		id - DOM pointer to the window element
		function - Optionally specify a function to be used to hide a box, such as a fading function, etc...

	Example:
		(start code)
			<input type="button" onclick="pax.box.hide(pax.$('myBox'), pax.fx.fadeOut );" value="Hide!">
			<input type='text' id='pax.box.hide.example1'>
			[:.
				pax.box.showOnRight( 'myBox', '<- Hello world!', 'hintMessage', pax.$('pax.box.hide.example1') );
			:]
		(end)
		
		This will hide a box, using the <pax.fx.fadeOut> method.
*/
pax.box.hide = function( box, func, callBack, duration ) {
	box = pax.$( box );
	if( ! box )return;
	var id = (typeof(box.id) != 'undefined' )? box.id: box;
	var funcPointer = null;
	
	if( box != null ) {
		if( func ) {
			//	Note: this assumes the hide function may have duration and callback
			funcPointer = func( id, duration, callBack );
		} else box.style.display='none';

		if( pax.isIe && pax.$( box.frameId ) )pax.$( box.frameId ).style.display='none';
	}
	return funcPointer;
};


/*	Method: pax.box.destroy
	This will destroy the given box
	
*/
pax.box.destroy = function( box ) {
	box = pax.$( box );
	if( box != null ) {
		box.style.display='none';
		if( pax.isIe && pax.$( box.frameId ) )pax.util.removeElement( pax.$( box.frameId ) );
		pax.util.removeElement( box );
	}
};